package sk.tuke.constraintbuilder.views.components;

import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.core.BinaryType;
import org.eclipse.jdt.internal.core.SourceType;
import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.wizards.BuildPathDialogAccess;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;

import sk.tuke.constraintbuilder.utils.MyImages;
import sk.tuke.constraintbuilder.utils.MyUtils;

public class TypeChooserPanel extends Composite {

	private final FormToolkit toolkit = new FormToolkit(Display.getCurrent());
	private Text text;
	private CLabel moveLabel;
	
	private boolean isArraySelected = false;
	private String clearText = "";

	/**
	 * Create the composite.
	 * @param parent
	 * @param style
	 */
	public TypeChooserPanel(Composite parent, int style) {
		super(parent, style);
		addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				toolkit.dispose();
			}
		});
		toolkit.adapt(this);
		toolkit.paintBordersFor(this);
		GridLayout gridLayout = new GridLayout(4, true);
		setLayout(gridLayout);
		

		
		final Composite bytePanel = new Composite(this, SWT.BORDER);
		GridLayout gl_bytePanel = new GridLayout(1, false);
		gl_bytePanel.marginWidth = 0;
		gl_bytePanel.verticalSpacing = 0;
		gl_bytePanel.marginHeight = 0;
		bytePanel.setLayout(gl_bytePanel);
		GridData gd_bytePanel = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
		gd_bytePanel.widthHint = 96;
		bytePanel.setLayoutData(gd_bytePanel);

		toolkit.adapt(bytePanel);
		toolkit.paintBordersFor(bytePanel);
		
		final Label lblByte = new Label(bytePanel, SWT.NONE);
		lblByte.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
		toolkit.adapt(lblByte, true, true);
		lblByte.setText("byte");
		TypeChooserMouseListener listener = new TypeChooserMouseListener(this);
		lblByte.addMouseTrackListener(listener);
		lblByte.addMouseListener(listener);
		addDNDListener(lblByte);
		
		Composite shortPanel = new Composite(this, SWT.BORDER);
		GridLayout gl_shortPanel = new GridLayout(1, false);
		gl_shortPanel.marginWidth = 0;
		gl_shortPanel.marginHeight = 0;
		shortPanel.setLayout(gl_shortPanel);
		shortPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		toolkit.adapt(shortPanel);
		toolkit.paintBordersFor(shortPanel);
		
		Label lblShort = new Label(shortPanel, SWT.NONE);
		lblShort.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		toolkit.adapt(lblShort, true, true);
		lblShort.setText("short");
		lblShort.addMouseTrackListener(listener);
		lblShort.addMouseListener(listener);
		addDNDListener(lblShort);
		
		Composite intPanel = new Composite(this, SWT.BORDER);
		GridLayout gl_intPanel = new GridLayout(1, false);
		gl_intPanel.marginWidth = 0;
		gl_intPanel.marginHeight = 0;
		intPanel.setLayout(gl_intPanel);
		intPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		toolkit.adapt(intPanel);
		toolkit.paintBordersFor(intPanel);
		
		Label lblInt = new Label(intPanel, SWT.NONE);
		lblInt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		toolkit.adapt(lblInt, true, true);
		lblInt.setText("int");
		lblInt.addMouseTrackListener(listener);
		lblInt.addMouseListener(listener);
		addDNDListener(lblInt);
		
		Composite longPanel = new Composite(this, SWT.BORDER);
		GridLayout gl_longPanel = new GridLayout(1, false);
		gl_longPanel.marginWidth = 0;
		gl_longPanel.marginHeight = 0;
		longPanel.setLayout(gl_longPanel);
		longPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		toolkit.adapt(longPanel);
		toolkit.paintBordersFor(longPanel);
		
		Label lblLong = new Label(longPanel, SWT.NONE);
		lblLong.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		toolkit.adapt(lblLong, true, true);
		lblLong.setText("long");
		lblLong.addMouseTrackListener(listener);
		lblLong.addMouseListener(listener);
		addDNDListener(lblLong);
		
		Composite floatPanel = new Composite(this, SWT.BORDER);
		GridLayout gl_floatPanel = new GridLayout(1, false);
		gl_floatPanel.marginWidth = 0;
		gl_floatPanel.marginHeight = 0;
		floatPanel.setLayout(gl_floatPanel);
		floatPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		toolkit.adapt(floatPanel);
		toolkit.paintBordersFor(floatPanel);
		
		Label lblFloat = new Label(floatPanel, SWT.NONE);
		lblFloat.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		toolkit.adapt(lblFloat, true, true);
		lblFloat.setText("float");
		lblFloat.addMouseTrackListener(listener);
		lblFloat.addMouseListener(listener);
		addDNDListener(lblFloat);
				
		Composite doublePanel = new Composite(this, SWT.BORDER);
		GridLayout gl_doublePanel = new GridLayout(1, false);
		gl_doublePanel.marginWidth = 0;
		gl_doublePanel.marginHeight = 0;
		doublePanel.setLayout(gl_doublePanel);
		doublePanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		toolkit.adapt(doublePanel);
		toolkit.paintBordersFor(doublePanel);
		
		Label lblDouble = new Label(doublePanel, SWT.NONE);
		lblDouble.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		toolkit.adapt(lblDouble, true, true);
		lblDouble.setText("double");
		lblDouble.addMouseTrackListener(listener);
		lblDouble.addMouseListener(listener);
		addDNDListener(lblDouble);
				
		Composite booleanPanel = new Composite(this, SWT.BORDER);
		GridLayout gl_composite_6 = new GridLayout(1, false);
		gl_composite_6.marginWidth = 0;
		gl_composite_6.marginHeight = 0;
		booleanPanel.setLayout(gl_composite_6);
		booleanPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		toolkit.adapt(booleanPanel);
		toolkit.paintBordersFor(booleanPanel);
		
		Label lblBoolean = new Label(booleanPanel, SWT.NONE);
		lblBoolean.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		toolkit.adapt(lblBoolean, true, true);
		lblBoolean.setText("boolean");
		lblBoolean.addMouseTrackListener(listener);
		lblBoolean.addMouseListener(listener);
		addDNDListener(lblBoolean);
				
		Composite charPanel = new Composite(this, SWT.BORDER);
		GridLayout gl_charPanel = new GridLayout(1, false);
		gl_charPanel.marginWidth = 0;
		gl_charPanel.marginHeight = 0;
		charPanel.setLayout(gl_charPanel);
		charPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		toolkit.adapt(charPanel);
		toolkit.paintBordersFor(charPanel);
		
		Label lblChar = new Label(charPanel, SWT.NONE);
		lblChar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		toolkit.adapt(lblChar, true, true);
		lblChar.setText("char");
		lblChar.addMouseTrackListener(listener);
		lblChar.addMouseListener(listener);
		addDNDListener(lblChar);
				
		Label customTypeLabel = new Label(this, SWT.NONE);
		toolkit.adapt(customTypeLabel, true, true);
		customTypeLabel.setText("Custom Type: ");
		
		text = new Text(this, SWT.BORDER);
		text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
		text.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				moveLabel.setText(text.getText());
			}
		});
		toolkit.adapt(text, true, true);
		addDNDListener(text);
		
		Button btnBrowse = new Button(this, SWT.NONE);
		toolkit.adapt(btnBrowse, true, true);
		btnBrowse.setText("Browse");
		btnBrowse.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				Shell shell = PlatformUI.getWorkbench().getModalDialogShellProvider().getShell();
				IRunnableContext context = PlatformUI.getWorkbench().getProgressService();
				IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
				try {
					SelectionDialog dialog = JavaUI.createTypeDialog(shell, context, scope, IJavaElementSearchConstants.CONSIDER_ALL_TYPES, false);
					dialog.open();
					Object[] results = dialog.getResult();
					
					System.out.println(results[0].getClass().getName());
					if(results[0] instanceof BinaryType){
						setText(((BinaryType)results[0]).getFullyQualifiedName());
					}
					if(results[0] instanceof SourceType){
						setText(((SourceType)results[0]).getFullyQualifiedName());
					}
				} catch (JavaModelException exc) {
					System.out.println("<Open Type Dialog> JavaModelException");
				}
			}
		});
		
		Button btnStandardType = new Button(this, SWT.RADIO);
		btnStandardType.setSelection(true);
		toolkit.adapt(btnStandardType, true, true);
		btnStandardType.setText("Standard Type");
		btnStandardType.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				isArraySelected = false;
				text.setText(clearText);
			}
		});
		
		Button btnArray = new Button(this, SWT.RADIO);
		toolkit.adapt(btnArray, true, true);
		btnArray.setText("Array");
		btnArray.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				isArraySelected = true;
				text.setText(clearText+"[]");
			}
		});
		
		Composite composite = new Composite(this, SWT.BORDER);
		GridLayout gl_composite = new GridLayout(1, false);
		gl_composite.marginHeight = 2;
		gl_composite.marginWidth = 2;
		composite.setLayout(gl_composite);
		composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1));
		toolkit.adapt(composite);
		toolkit.paintBordersFor(composite);
		
		moveLabel = new CLabel(composite, SWT.NONE);
		moveLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		toolkit.adapt(moveLabel);
		toolkit.paintBordersFor(moveLabel);
		moveLabel.setText("Choose Type");
		moveLabel.setImage(MyImages.MOVE);
		addDNDListener(moveLabel);

	}
	
	private void addDNDListener(Control control){
		int operations = DND.DROP_MOVE | DND.DROP_COPY;
		Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
		DragSourceListener listener = new DragSourceAdapter() {
			@Override
			public void dragSetData(DragSourceEvent event) {
				DragSource ds = (DragSource) event.widget;
				if(ds.getControl() instanceof Label){
					Label label = (Label) ds.getControl();
					if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
						if(isArraySelected){
							event.data = label.getText()+"[]";
						}
						else{
							event.data = label.getText();
						}	
					}
				}
				else if(ds.getControl() instanceof CLabel){
					CLabel label = (CLabel) ds.getControl();
					if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
						event.data = label.getText();
					}
				}
			}
		};
		DragSource source = new DragSource(control, operations);
		source.setTransfer(types);
		source.addDragListener(listener);
	}

	public void setText(String string) {
		clearText = string;
		if(isArraySelected){
			text.setText(clearText+"[]");
		}
		else{
			text.setText(clearText);
		}
		
	}

}
